<?php
/**
 * TinyCorePHP 公共函数库
 * @author 	kelecode@gmail.com
 * @date 		2012-12-18
 */

/**
 * 读取/设置 config.php文件中$config的值，最多支持二维数组
 * @param string $key
 * @param string $value 
 */
function C($key, $value=''){
	require_once 'config.php';
	global $tiny_config;
	$config = $tiny_config;
	if(!empty($key)){
		$temp = explode('.',$key);
		if(is_array($temp) && count($temp) > 1){
			if(!empty($value)){
				return $config[$temp[0]][$temp[1]] = $value;
			}
			return $config[$temp[0]][$temp[1]];	
		}else{
			if(!empty($value)){
				return $config[$key] = $value;
			}
			return $config[$key];
		}
	}
}

/**
 * 加载指定的插件
 * @param string $flug_name 插件名称
 * @param int $flug_id 插件id
 * @param int $alias 插件别名
 */
function P($flug_name,$flug_id=null,$alias=null){
	$flug_name = strtolower($flug_name);
	$file = APP_ROOT.'/plugin/plu_'.$flug_name.'/app.php';
	if(file_exists($file)){
		include $file;
	}else{
		echo 'plugin not found.';
	}
}

function M($model_name,$component=null){
	if(empty($model_name)){
		return false;
	}
	$model_name = ucfirst($model_name).'Model';
	$component = !empty($component) ? (string)$component : (string)trim($_GET['com']);
	if( ! empty($component) && $model_name != 'UserModel' ){
		$model_path = 'component/com_' . strtolower($component) . '/model';
	}else{
		$model_path = 'model';
	}	
	$model_file = $model_name . '.class.php';
	import($model_path,$model_file);
	$model = new $model_name();

	return $model;
}

/**
 * 载入指定的扩展(组件 or 插件)
 * @param string $obj e.g.  com.links.links.index
 */
function E($obj){
	$temp = explode('.',$obj);
	if('com' == strtolower($temp[0])){
		$component = trim($temp[1]);
		$c = trim($temp[2]);
		$m = trim($temp[3]);
		$control = empty($c) ? 'index' : $c;
		$method = empty($m) ? 'index' : $m;
		$className = ucfirst($control).'Control';
		$file = APP_ROOT . '/component/com_' . strtolower($component) . '/control/' . $className . '.class.php';
		(file_exists($file) && require_once $file) or die('File "' . $className . '.class.php" not found.');
		if(class_exists($className)){
			$class = new $className();
			if(method_exists($class,$method) || (method_exists($class,'index') && $method = 'index')){
				call_user_func(array($class,$method));
			}else{
				die('Method '.$method.' not found.');
			}
		}else{
			die('Class '.$className.' not found.');
		}
	}else if('plug' == strtolower($temp[0])){	
		//TODO
	}else{	
		die();
	}
}

function import($path, $file){
	$path = APP_ROOT . '/' . $path . '/';
	if(file_exists($path . $file)){
		require_once $path . $file;
	}else{
		die('file ' . $file . ' not found.');
	}
}

/**
 * 调试
 */
function debug($data=null){
	if( ! empty($data)){
		echo '<pre style="border:1px dashed #999;padding:5px;">';
		var_dump($data);
		echo '</pre>';
	}else{
		echo 'debug';
	}
}

//生成提交表单时用的token
function token(){
	return md5(time());
}

//URL重定向
function redirect($url,$time=0,$msg='',$charset='UTF-8'){
	//多行URL地址支持
    $url = str_replace(array("\n", "\r"), '', $url);
    if(empty($msg)){
        $msg    =   "系统将在{$time}秒之后自动跳转到{$url}！";
    }
	$charset = strtoupper($charset);
	if( is_utf8($msg) && ($charset == 'GBK' || $charset == 'GB2312') ){
		$msg = auto_charset($msg,'utf-8','gbk');
	}else if( !is_utf8($msg) && ($charset == 'UTF-8' || $charset == 'UTF8') ){
		$msg = auto_charset($msg,'gbk','utf-8');
	}	
	if (!headers_sent()) {
        if(0 === $time) {
            header("Location: ".$url);
        }else {
            header("refresh:{$time};url={$url}");
			$msg = '<meta http-equiv="Content-Type" content="text/html; charset='.$charset.'"/>'.$msg;
			echo($msg);
        }
        exit();
    }else {
		$str = '<meta http-equiv="Content-Type" content="text/html; charset='.$charset.'"/>';
        $str .= "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
		$str .= 0 === $time ? '' : $msg;
        exit($str);
    }
}

/**
 * Ajax方式返回数据到客户端
 * @param mixed $data 要返回的数据
 * @param String $info 提示信息
 * @param boolean $status 返回状态
 * @param String $status ajax返回类型 JSON XML
 * @return void
 */
function ajaxReturn($data,$info='',$status=1,$type='JSON'){
	$result = array();
	$result['status']  =  $status;
	$result['info'] =  $info;
	$result['data'] = $data;
	if(strtoupper($type)=='JSON'){
		// 返回JSON数据格式到客户端 包含状态信息
		header("Content-Type:text/html; charset=utf-8");
		exit(json_encode($result));
	}elseif(strtoupper($type)=='XML'){
		// 返回xml格式数据
		header("Content-Type:text/xml; charset=utf-8");
		exit(xml_encode($result));
	}elseif(strtoupper($type)=='EVAL'){
		// 返回可执行的js脚本
		header("Content-Type:text/html; charset=utf-8");
		exit($data);
	}
}

/**
 * 生成指定数量的验证码
 * @param 	int $len 验证码长度
 * @param 	int $num 验证码个数
 * @param 	array $code 验证码数组
 */
function make_code($len=6,$num=5,$code=null){
	$len = $len < 0 ? 6 : $len;
	$num = $num < 0 ? 5 : $num;
	for($i=0;$i<$num;$i++){
		$code[] = rand_chars($len);
	}
	
	//去重,若个数不够则递归生成验证码
	$code = array_unique($code);
	if(count($code) < $num){
		$code = make_code($len, $num-count($code),$code);
	}
	
	return $code;
}

/**
 * 生成指定长度的随机字符串
 * @param 	int $len 字符串长度
 * @return 	string $str
 */
function rand_chars($len=6){
    $str ='';
    $chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
    $chars = $len > 10 ? str_repeat($chars,5) : $chars;
	$chars = str_shuffle($chars);
	$str = substr($chars,0,$len);
	
    return $str;
}

/**
 * 强制创建目录
 */
function forcemkdir($path) {
	if(!file_exists($path)){
		forcemkdir(dirname($path));
		mkdir($path,0777);
		@chmod($path,0755);
	}
}

//获取客户端IP地址
function get_client_ip(){
	if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")){
		$ip = getenv("HTTP_CLIENT_IP");
	}else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")){
		$ip = getenv("HTTP_X_FORWARDED_FOR");
	}else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")){
		$ip = getenv("REMOTE_ADDR");
	}else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")){
		$ip = $_SERVER['REMOTE_ADDR'];
	}else{
		$ip = "unknown";
	}
	
	//若取到的ip是由逗号分隔的多个值则只取第一个。如：113.250.80.227, 192.168.52.22
	$ip = trim($ip);
	if( !empty($ip) && $ip != 'unknown'){
		$ip = explode(',',$ip);
		$ip = $ip[0];
	}

	return($ip);
}

/**
* 检查字符串是否是UTF8编码
* @param string $string 字符串
* @return Boolean
**/
function is_utf8($str) {
    $c=0; $b=0;
    $bits=0;
    $len=strlen($str);
    for($i=0; $i<$len; $i++){
	    	$c=ord($str[$i]);
	    	if($c > 128){
	            if(($c >= 254)) return false;
	            elseif($c >= 252) $bits=6;
	            elseif($c >= 248) $bits=5;
	            elseif($c >= 240) $bits=4;
	            elseif($c >= 224) $bits=3;
	            elseif($c >= 192) $bits=2;
	            else return false;
	            if(($i+$bits) > $len) return false;
	            while($bits > 1){
	                    $i++;
	                    $b=ord($str[$i]);
	                    if($b < 128 || $b > 191) return false;
	                    $bits--;
	            }
	    	}
    }
		return true;
}

//自动转换字符集 支持数组转换
function auto_charset($fContents,$from='gbk',$to='utf-8'){
    $from = strtoupper($from)=='UTF8'? 'utf-8':$from;
    $to = strtoupper($to)=='UTF8'? 'utf-8':$to;
    if( strtoupper($from) === strtoupper($to) || empty($fContents) || (is_scalar($fContents) && !is_string($fContents)) ){
        //如果编码相同或者非字符串标量则不转换
        return $fContents;
    }
    if(is_string($fContents) ) {
        if(function_exists('mb_convert_encoding')){
            return mb_convert_encoding ($fContents, $to, $from);
        }elseif(function_exists('iconv')){
            return iconv($from,$to,$fContents);
        }else{
            return $fContents;
        }
    }
    elseif(is_array($fContents)){
        foreach ( $fContents as $key => $val ) {
            $_key =     auto_charset($key,$from,$to);
            $fContents[$_key] = auto_charset($val,$from,$to);
            if($key != $_key )
                unset($fContents[$key]);
        }
        return $fContents;
    }
    else{
        return $fContents;
    }
}

/**
 * 输出纯文本
 * @param string $text
 * @param bool $parseBr 
 * @return string $text
 */
function text($text,$parseBr=false){
	if(!$parseBr){
		$text = str_replace(array("\r","\n","\t"),' ',$text);
	}else{
		$text = nl2br($text);
	}
	$text = stripslashes($text);
	$text = htmlspecialchars($text, ENT_NOQUOTES,'utf-8');

	return $text;
}

function daddslashes($string, $force = 0, $strip = FALSE) {
	if(!get_magic_quotes_gpc() || $force) {
		if(is_array($string)) {
			foreach($string as $key => $val) {
				$string[$key] = daddslashes($val, $force, $strip);
			}
		} else {
			$string = addslashes($strip ? stripslashes($string) : $string);
		}
	}
	return $string;
}

function getgpc($k, $var='R') {
	switch($var) {
		case 'G': $var = &$_GET; break;
		case 'P': $var = &$_POST; break;
		case 'C': $var = &$_COOKIE; break;
		case 'R': $var = &$_REQUEST; break;
	}
	return isset($var[$k]) ? $var[$k] : NULL;
}

/**
 * 格式化内存使用大小
 *
 * @param   int    $size
 * @param   string $format   The format to display (printf format)
 * @param   int    $round
 * @return  string
 */
function readableSize($size, $format = null, $round = 3){
	$mod = 1024;
	$units = explode(' ','B Kb Mb Gb Tb');

	if(is_null($format)){
		$format = '%.2f%s';
	}
	for($i = 0; $size > $mod; $i++){
		$size /= $mod;
	}
	if(0 === $i){
		$format = preg_replace('/(%.[\d]+f)/', '%d', $format);
	}

	return sprintf($format, round($size, $round), $units[$i]);
}

/**
 * 格式化时间
 *
 * @param  float $microtime
 * @param  string  $format   The format to display (printf format)
 * @return string
 */
function readableElapsedTime($microtime, $format = null, $round = 3){
	if( is_null($format) ){
		$format = '%.3f%s';
	}

	if($microtime >= 1){
		$unit = 's';
		$time = round($microtime, $round);
	}else{
		$unit = 'ms';
		$time = round($microtime*1000);
		$format = preg_replace('/(%.[\d]+f)/', '%d', $format);
	}

	return sprintf($format, $time, $unit);
}
	
/**
 * 显示代码执行时间和内存使用情况等
 */
function runInfo($return=false){
	global $startTime;
	$endTime = microtime(true);	
	$usedTime = $endTime - $startTime;
	$usedTime = readableElapsedTime($usedTime);	
	$usedMemory = memory_get_usage(true);
	$usedMemory = readableSize($usedMemory,'%.3f%s');
	
	if($return){
		return array('usedTime'=> $usedTime, 'usedMemory'=>$usedMemory);
	}
	echo '<b>time used: </b>'.$usedTime , ', <b>memory used:</b>'.$usedMemory;
}

function tinySubstr($str, $start=0, $limit=12){
	if('gbk'==strtolower(WIKI_CHARSET)){
		$strlen=strlen($str);
		if ($start>=$strlen){
			return $str;
		}
		$clen=0;
		for($i=0;$i<$strlen;$i++,$clen++){
			if(ord(substr($str,$i,1))>0xa0){
				if ($clen>=$start){
					$tmpstr.=substr($str,$i,2);
				}
				$i++;
			}else{
				if ($clen>=$start){
					$tmpstr.=substr($str,$i,1);
				}
			}
			if ($clen>=$start+$limit){
				break;
			}
		}
		$str=$tmpstr;
	}else{
		$patten = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
		preg_match_all($patten, $str, $regs);
		$v = 0; $s = '';
		for($i=0; $i<count($regs[0]); $i++){
			(ord($regs[0][$i]) > 129) ? $v += 2 : $v++;
			$s .= $regs[0][$i];
			if($v >= $limit * 2){
				break;
			}
		}
		$str=$s;
	}
	return $str;
}


/**
 * 根据数据库配置获取数据库链接资源
 *
 * @param array $dbConfig   数据库链接配置
 * @return object $dbLink   数据库链接对象
 */
function getDbLink($dbConfig){
	$dbLink = mysql_connect($dbConfig['db_host'],$dbConfig['db_user'],$dbConfig['db_pswd']);
	$dbLink &&  mysql_select_db($dbConfig['db_name'],$dbLink);
	mysql_query("SET character_set_connection=UTF8, character_set_results=UTF8, character_set_client=binary", $dbLink);
	mysql_query("SET sql_mode=''", $dbLink);		

	return $dbLink;
}

/**
 * 执行指定的sql
 * @param string $sql
 * @return bool $result
 */
function execute($sql){
	if( empty($sql) ){
		return false;
	}
	$result = null;
	$dbLink = getDbLink(C('dbw'));
	$result = mysql_query($sql,$dbLink);
	mysql_close($dbLink);

	return $result;
}

/**
 * 执行sql返回执行结果集
 *
 * @param string $sql
 * @param string $field 用于获取字段
 * @return arrary $data
 */
function query($sql,$field=null){
	if( empty($sql) ){
		return array();
	}
	
	$data = array();
	$dbLink = getDbLink(C('dbr'));
	$result = mysql_query($sql,$dbLink);
	while($rs = mysql_fetch_array($result, MYSQL_ASSOC)){
		$data[] = empty($field) ? $rs : $rs[$field];
	}
	mysql_close($dbLink);

	return $data;
}

